/* The Generic Stack.  Works like a stack
 * Tyler Wozniak & Andrew Hall
 */

#ifndef STACK
#define STACK
#include "imports.h"
#include "Node.h"

template <typename T>
class Stack
{
private:
	int size; //The size of the stack
	Node<T>* top; //The top node pointer
public:
	//Returns the current length of the stack
	int Length() const
	{
		return size;
	}

	//Default constructor
	Stack()
	{
		size = 0;
		top = NULL;
	}

	//Push, implemented with += operator
	void operator+=(T data)
	{
		Node<T>* nodeToBeAdded = new Node<T>(data, size);
		nodeToBeAdded->nextNode = top;
		top = nodeToBeAdded;

		size++;
	}

	//Removes the top element from the stack, and returns that element
	T operator--()
	{
		Node<T>* temp = NULL;
		if(top)
		{
			temp = top;
			top = top->nextNode;
			size--;
			T retData = temp->data;
			delete temp;
			return retData;
		}
		return T();
	}

	//Returns the top element without removing it
	T peek() const
	{
		if(top)
		{
			return top->data;
		}
		else
			return NULL;
	}

	//Returns if the stack is empty
	inline bool isEmpty() const
	{
		return !size;
	}

	//Clears all elements of the stack
	void clear()
	{
		while(top)
		{
			--(*this);
		}
	}

	//Deep Copy constructor
	Stack(const Stack<T>& other)
	{
		Stack tempStack;
		Node<T>* tempNode = other.top;
		while(tempNode)
		{
			tempStack += other.top->data;
			tempNode = tempNode->nextNode;
		}
		while(tempStack.top)
		{
			this += tempStack--;
		}
	}

	//Copy assignment operator
	Stack<T> operator=(const Stack<T>& other)
	{
		clear();
		Stack tempStack;
		Node<T>* tempNode = other.top;
		while(tempNode)
		{
			tempStack += other.top->data;
			tempNode = tempNode->nextNode;
		}
		while(tempStack.top)
		{
			this += tempStack--;
		}

		return *this;
	}

	//Destructor
	~Stack()
	{
		clear();
	}
};

#endif